package com.darwin.darwinDll.analyze
{
	import com.darwin.darwinDll.core.DllItem;
	
	import flash.display.Loader;
	import flash.events.Event;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import flash.utils.describeType;
	import flash.utils.setTimeout;
	
	/**
	 * Swf解析器
	 * @author Roland
	 */
	public class SwfAnalyze implements IAnalyze
	{
		public function SwfAnalyze()
		{

		}
		
		private var _mainAppDomain:ApplicationDomain;
		private var _mainLoader:Loader;
		private var  _appDomainList:Array = [];
		private var _appDomainDic:Dictionary = new Dictionary();
		private var _swfDic:Dictionary = new Dictionary();

		private var _byteArray:ByteArray;
		private var _compFnList:Dictionary = new Dictionary();
		private var _dllItemList:Dictionary = new Dictionary();
		
		public function analyze(byteArray:ByteArray, dllItem:DllItem, compFn:Function):void
		{
			var loader:Loader = new Loader();
			_byteArray = byteArray;
			_compFnList[loader] = compFn;
			_dllItemList[loader] = dllItem;
			var lc : LoaderContext = new LoaderContext();
			lc.allowCodeImport = true;
			loader.loadBytes(byteArray,lc);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onCompletefunc);
		}
		
		private function  onCompletefunc(e:Event):void
		{
			var targetLoader:Loader = e.target.loader;// as Loader;
			e.target.removeEventListener(Event.COMPLETE,onCompletefunc);
			var dllItem:DllItem = _dllItemList[targetLoader]
			dllItem.data = _byteArray;
			dllItem.result = targetLoader;
			_swfDic[dllItem.name] = targetLoader;
			dllItem.status = DllItem.STATUS_LOADED;
			_appDomainDic[dllItem.name] = e.currentTarget.applicationDomain;
			_appDomainList.push(e.currentTarget.applicationDomain);
			
			if(dllItem.name == "main")
			{
				_mainLoader = targetLoader;
				_mainAppDomain = e.currentTarget.applicationDomain;
			}
			
			var compFn:Function = _compFnList[targetLoader];
			if(compFn!=null)
			{
				compFn(dllItem);
			}
			
			delete _dllItemList[targetLoader];
			delete _compFnList[targetLoader];
			dllItem = null;
//			_compFn = null;
			_byteArray = null;
			targetLoader = null;
		}
		
		/**
		 *	返回导出类 
		 * @param key 文件名
		 * @param subKey 导出类类名
		 * @return 
		 * 
		 */
		public function getData(key:String, subKey:String):*
		{
			if(subKey != "" && subKey != null)
			{
				if(key != "" && key != null)
				{
					return getClassInDomainByName(key,subKey);
				}else{
					return getClassByName(subKey);
				}
			}else if(key != "" && key != null)
			{
				return _swfDic[key];
			}
			return null;
		}
		
		public function getDataList():Dictionary
		{
			return _swfDic;
		}
		
		
		/**
		 *	 如果此解析器解析过main文件,则此处返回main文件的Loader
		 * @return 
		 * 
		 */
		public function get mainLoader():Loader
		{
			return _mainLoader;
		}
		
		/**
		 *	如果此解析器解析过main文件,则此处返回main文件的 ApplicationDomain
		 * @return 
		 * 
		 */
		public function get mainAppDomain():ApplicationDomain
		{
			return _mainAppDomain;
		}
		
		/**
		 *	在特定的appDomain中获取类定义 
		 * @param appDomainkey
		 * @param name
		 * @return 
		 * 
		 */
		private function getClassInDomainByName(appDomainkey:String,name:String):Class
		{
			var returnClass:Class;
			var appDomain:ApplicationDomain = _appDomainDic[appDomainkey];
			if(appDomain == null)
			{
				appDomain = _appDomainDic[appDomainkey + "$" + name];
			}
			if(appDomain && appDomain.hasDefinition(name))
			{
				returnClass = appDomain.getDefinition(name) as Class;
				_returnClassDic[name] = returnClass;
			}
			return returnClass;
		}
		
		private var _returnClassDic:Dictionary = new Dictionary();
		/**
		 *返回类 
		 * @param name
		 * @return 
		 * 
		 */		
		private  function getClassByName(name:String):Class
		{
			if(_returnClassDic[name])
			{
				return _returnClassDic[name];
			}
			var returnClass:Class;
			var index:int = 0;
			var appDomain:ApplicationDomain;
			for each(appDomain in _appDomainList) 
			{
				if(appDomain.hasDefinition(name))
				{
					returnClass = appDomain.getDefinition(name) as Class;
					_returnClassDic[name] = returnClass;
					break;
				}
			}

			return (returnClass?returnClass:null);
		}
	}
}